home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 October: Mac OS SDK / Dev.CD Oct 00 SDK1.toast / Development Kits / Mac OS / Navigation Services SDK / Examples / Sampler / Sampler ƒ / menus.c < prev    next >
Encoding:
Text File  |  1999-06-16  |  43.6 KB  |  1,576 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        menus.c
  3.  
  4.     Copyright:    © 1997-1998 by Apple Computer, Inc., all rights reserved.
  5.  
  6. */
  7.  
  8. //    
  9. //    You may incorporate this sample code into your applications
  10. //    without restriction. This sample code has been provided "AS
  11. //    IS" and the responsibility for its operation is 100% yours.
  12. //    You are not permitted to redistribute the source as "Apple
  13. //    sample code" after having made changes. If you're going to
  14. //    re-distribute the source, we require that you make it clear
  15. //    in the source that the code was descended from Apple sample
  16. //    code, but that you've made changes.
  17. //    
  18.     
  19. #pragma segment AppSeg
  20.  
  21. #ifndef __SCRAP__
  22. #include <Scrap.h>
  23. #endif
  24.  
  25. #ifndef __DEVICES__
  26. #include <Devices.h>
  27. #endif
  28.  
  29. #ifndef __TOOLUTILS__
  30. #include <ToolUtils.h>
  31. #endif
  32.  
  33. #ifndef __LISTS__
  34. #include <Lists.h>
  35. #endif
  36.  
  37. #ifndef __SOUND__
  38. #include <Sound.h>
  39. #endif
  40.  
  41.  
  42. #ifndef Common_Defs
  43. #include "Common.h"
  44. #endif
  45.  
  46.  
  47. // prototypes:
  48. void SetItemEnable( MenuHandle theMenu, short theItem, short enable );
  49. short DoPaste( );
  50. void DoAbout( );
  51.  
  52. // protos for using the Nav dialogs:
  53. OSErr DoSelectDictionary( void );
  54. OSErr DoSelectDirectory( void );
  55. OSErr DoSelectObject( void );
  56. OSErr DoSelectVolume( void );
  57. OSErr DoCreateFolder( void );
  58.  
  59. // open customization example:
  60. OSErr DoCustomOpen( void );
  61. pascal void myCustomEventProc( NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, NavCallBackUserData callBackUD );
  62. void HandleCustomMouseDown( NavCBRecPtr callBackParms );
  63. void HandleCommandPopup( ControlHandle thePopup, NavCBRecPtr callBackParms );
  64.  
  65. // for add/remove example:
  66. pascal void myCustomAddRemoveEventProc(    NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, NavCallBackUserData callBackUD );
  67. void HandleAddRemoveCustomMouseDown( NavCBRecPtr callBackParms );
  68. OSErr DoCustomAddRemove( void );
  69. Boolean DoListMouseDown( NavCBRecPtr callBackParms );
  70. void HandleAdd( NavCBRecPtr callBackParms, AEDescList fileList );
  71. void HandleRemove( NavCBRecPtr callBackParms );
  72. void HandleRemoveAll( NavCBRecPtr callBackParms );
  73. Boolean DoAddItem( unsigned char* theData, short size );
  74. void AdjustAddButton( NavCBRecPtr callBackParms );
  75. Boolean DoSearch( AEDesc searchDesc );
  76.  
  77. // custom dialog item:
  78. #define kControlListID            132
  79. #define kPopupCommand             1
  80.  
  81. #define kAddRemoveControlListID    133
  82. #define iList                    1
  83. #define iAddButton                2
  84. #define iRemoveButton            3
  85. #define iRemoveAllButton        4
  86. #define iDoneButton                5
  87.  
  88. // the requested dimensions for our sample open customization area:
  89. #define kCustomWidth            100
  90. #define kCustomHeight            40
  91.  
  92. // the requested dimensions for our add remove customization area:
  93. #define kAddRemoveCustomWidth    400
  94. #define kAddRemoveCustomHeight    125
  95.                 
  96. extern Document* gDocumentList[kMaxDocumentCount];
  97. extern short    gDocumentCount;
  98. extern short    gCanUndoDrag;
  99. extern short    gQuit, gQuitting;
  100. extern Boolean    gNavServicesExists;
  101.  
  102. // customization globals:
  103. Handle         gDitlList;
  104. MenuHandle     gPopupMenu;
  105. short         gLastTryWidth;
  106. short         gLastTryHeight;
  107. ListHandle    gListItem;
  108. long        gNumItems;
  109. Rect        gOriginalRect;
  110.  
  111.  
  112. // *****************************************************************************
  113. // *
  114. // *    SetItemEnable()
  115. // *
  116. // *****************************************************************************
  117. void SetItemEnable(MenuHandle theMenu, short theItem, short enable)
  118. {
  119.     if (enable)
  120.         EnableItem(theMenu,theItem);
  121.     else
  122.         DisableItem(theMenu,theItem);
  123. }
  124.  
  125.  
  126. // *****************************************************************************
  127. // *
  128. // *    AdjustMenus()
  129. // *
  130. // *****************************************************************************
  131. void AdjustMenus()
  132. {    
  133.     MenuHandle    theMenu;
  134.     Document*    theDocument;
  135.     short        teSelection = 0;
  136.     Str255        theStr;
  137.  
  138.     theDocument = IsDocumentWindow((WindowPtr)FrontWindow());
  139.     
  140.     if (theDocument->theTE != NULL)
  141.         teSelection = (theDocument) && ((**(theDocument->theTE)).selStart != (**(theDocument->theTE)).selEnd);
  142.  
  143.     theMenu = GetMenuHandle(idFileMenu);
  144.  
  145.     SetItemEnable(theMenu,NewItem,gDocumentCount < kMaxDocumentCount);
  146.     SetItemEnable(theMenu,OpenItem,gDocumentCount < kMaxDocumentCount);
  147.  
  148.     SetItemEnable(theMenu,CloseItem,theDocument != 0L);
  149.     SetItemEnable(theMenu,SaveItem,(theDocument) && (theDocument->dirty));
  150.     SetItemEnable(theMenu,RevertItem,(theDocument) && (theDocument->dirty) && (theDocument->fRefNum));
  151.     SetItemEnable(theMenu,SaveACopyItem,theDocument != 0L);
  152.     SetItemEnable(theMenu,DictionaryItem,gNavServicesExists);
  153.  
  154.     theMenu = GetMenuHandle(idEditMenu);
  155.  
  156.     GetIndString(theStr,MenuStringsID,gCanUndoDrag);
  157.     SetMenuItemText(theMenu,iUndo,theStr);
  158.     SetItemEnable(theMenu,iUndo,gCanUndoDrag != slCantUndo);
  159.  
  160.     SetItemEnable(theMenu,iCut,teSelection);
  161.     SetItemEnable(theMenu,iCopy,teSelection);
  162.     SetItemEnable(theMenu,iPaste,theDocument != 0L);
  163.     SetItemEnable(theMenu,iClear,teSelection);
  164.     SetItemEnable(theMenu,iSelectAll,theDocument != 0L);
  165.  
  166.     theMenu = GetMenuHandle(idUtilsMenu);
  167.     SetItemEnable(theMenu,iSelectDir,gNavServicesExists);
  168.     SetItemEnable(theMenu,iSelectVol,gNavServicesExists);
  169.     SetItemEnable(theMenu,iSelectObject,gNavServicesExists);
  170.     SetItemEnable(theMenu,iCreateFolder,gNavServicesExists);
  171.     SetItemEnable(theMenu,iCustomOpen,gNavServicesExists);
  172.     SetItemEnable(theMenu,iAddFiles,gNavServicesExists);
  173. }
  174.  
  175.  
  176. // *****************************************************************************
  177. // *
  178. // *    DoPaste()
  179. // *
  180. // *****************************************************************************
  181. short DoPaste()
  182. {    
  183.     long    size, offset;
  184.     Handle    theData;
  185.  
  186.     size = GetScrap(0L,'UPRC',&offset);
  187.  
  188.     if (size <= 0)
  189.         return(0);
  190.  
  191.     theData = NewHandle(size);
  192.     GetScrap(theData,'UPRC',&offset);
  193.  
  194.     HLock(theData);
  195.     PutScrap(size,'test',*theData);
  196.  
  197.     HUnlock(theData);
  198.     DisposeHandle(theData);
  199.  
  200.     return noErr;
  201. }
  202.  
  203.  
  204. // *****************************************************************************
  205. // *
  206. // *    DoSelectDictionary()
  207. // *    
  208. // *****************************************************************************
  209. OSErr DoSelectDictionary()
  210. {    
  211.     NavReplyRecord        theReply;
  212.     NavDialogOptions    dialogOptions;
  213.     OSErr                theErr = noErr;
  214.     NavEventUPP            eventUPP = NewNavEventProc(myEventProc);
  215.     NavTypeListHandle    openList = NULL;
  216.     
  217.     // use the default location for the dialog:
  218.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  219.  
  220.     GetIndString(dialogOptions.message,rAppStringsID,sChooseFile);
  221.  
  222.     dialogOptions.preferenceKey = kSelectFilePrefKey;
  223.     
  224.     openList = (NavTypeListHandle)GetResource(kOpenRsrcType,kOpenRsrcID2);
  225.         
  226.     theErr = NavChooseFile(    NULL,
  227.                             &theReply,
  228.                             &dialogOptions,
  229.                             eventUPP,
  230.                             NULL,
  231.                             NULL,
  232.                             openList,
  233.                             (NavCallBackUserData)&gDocumentList);
  234.     
  235.     DisposeRoutineDescriptor(eventUPP);
  236.     
  237.     if ( theReply.validRecord && theErr == noErr )
  238.         {
  239.         // grab the target FSSpec from the AEDesc:    
  240.         FSSpec    finalFSSpec;    
  241.         AEDesc     resultDesc;
  242.  
  243.         if ((theErr = AECoerceDesc( &(theReply.selection), typeFSS, &resultDesc )) == noErr)
  244.             if ((theErr = AEGetDescData ( &resultDesc, NULL, &finalFSSpec, sizeof ( FSSpec ), NULL )) == noErr)
  245.                 {
  246.                 // 'finalFSSpec' is the chosen file…
  247.                 }
  248.         AEDisposeDesc(&resultDesc);
  249.         
  250.         theErr = NavDisposeReply(&theReply);
  251.         }
  252.     
  253.     if (openList != NULL)
  254.         DisposeHandle((Handle)openList);
  255.         
  256.     return theErr;
  257. }
  258.  
  259.  
  260. // *****************************************************************************
  261. // *
  262. // *    DoSelectDirectory()
  263. // *    
  264. // *****************************************************************************
  265. OSErr DoSelectDirectory()
  266. {    
  267.     NavReplyRecord        theReply;
  268.     NavDialogOptions    dialogOptions;
  269.     OSErr                theErr = noErr;
  270.     NavEventUPP            eventUPP = NewNavEventProc(myEventProc);
  271.     
  272.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  273.     
  274.     GetIndString(dialogOptions.message,rAppStringsID,sChooseFolder);
  275.     
  276.     dialogOptions.preferenceKey = kSelectFolderPrefKey;
  277.     
  278.     theErr = NavChooseFolder(    NULL,
  279.                                 &theReply,
  280.                                 &dialogOptions,
  281.                                 eventUPP,
  282.                                 NULL,
  283.                                 (NavCallBackUserData)&gDocumentList);
  284.     
  285.     DisposeRoutineDescriptor(eventUPP);
  286.  
  287.     if ((theReply.validRecord)&&(theErr == noErr))
  288.         {
  289.         // grab the target FSSpec from the AEDesc:    
  290.         FSSpec    finalFSSpec;    
  291.         AEDesc     resultDesc;
  292.  
  293.         if ((theErr = AECoerceDesc(&(theReply.selection),typeFSS,&resultDesc)) == noErr)
  294.             if ((theErr = AEGetDescData ( &resultDesc, NULL, &finalFSSpec, sizeof ( FSSpec ), NULL )) == noErr)
  295.                 {
  296.                 // 'finalFSSpec' is the selected directory…
  297.                 }
  298.         AEDisposeDesc(&resultDesc);
  299.         
  300.         theErr = NavDisposeReply(&theReply);
  301.         }
  302.         
  303.     return theErr;
  304. }
  305.  
  306.  
  307. // *****************************************************************************
  308. // *
  309. // *    DoSelectObject()
  310. // *    
  311. // *****************************************************************************
  312. OSErr DoSelectObject()
  313. {    
  314.     NavReplyRecord        theReply;
  315.     NavDialogOptions    dialogOptions;
  316.     OSErr                theErr = noErr;
  317.     NavEventUPP            eventUPP = NewNavEventProc(myEventProc);
  318.     
  319.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  320.     
  321.     GetIndString(dialogOptions.message,rAppStringsID,sChooseObject);
  322.     
  323.     dialogOptions.preferenceKey = kSelectObjectPrefKey;
  324.     
  325.     theErr = NavChooseObject(    NULL,
  326.                                 &theReply,
  327.                                 &dialogOptions,
  328.                                 eventUPP,
  329.                                 NULL,
  330.                                 (NavCallBackUserData)&gDocumentList);
  331.     
  332.     DisposeRoutineDescriptor(eventUPP);
  333.  
  334.     if ((theReply.validRecord)&&(theErr == noErr))
  335.         {
  336.         // grab the target FSSpec from the AEDesc:    
  337.         FSSpec    finalFSSpec;    
  338.         AEDesc     resultDesc;
  339.  
  340.         if ((theErr = AECoerceDesc(&(theReply.selection),typeFSS,&resultDesc)) == noErr)
  341.             if ((theErr = AEGetDescData ( &resultDesc, NULL, &finalFSSpec, sizeof ( FSSpec ), NULL )) == noErr)
  342.                 {
  343.                 // 'finalFSSpec' is the selected directory…
  344.                 }
  345.         AEDisposeDesc(&resultDesc);
  346.         
  347.         theErr = NavDisposeReply(&theReply);
  348.         }
  349.         
  350.     return theErr;
  351. }
  352.  
  353.  
  354.  
  355. // *****************************************************************************
  356. // *
  357. // *    DoSelectVolume()
  358. // *    
  359. // *****************************************************************************
  360. OSErr DoSelectVolume()
  361. {    
  362.     NavReplyRecord        theReply;
  363.     NavDialogOptions    dialogOptions;
  364.     OSErr                theErr = noErr;
  365.     NavEventUPP            eventUPP = NewNavEventProc(myEventProc);
  366.     
  367.     // use the default location for the dialog:
  368.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  369.     
  370.     GetIndString(dialogOptions.message,rAppStringsID,sChooseVolume);
  371.  
  372.     dialogOptions.preferenceKey = kSelectVolumePrefKey;
  373.     
  374.     theErr = NavChooseVolume(    NULL,
  375.                                 &theReply,
  376.                                 &dialogOptions,
  377.                                 eventUPP,
  378.                                 NULL,
  379.                                 (NavCallBackUserData)&gDocumentList);
  380.     if ((theReply.validRecord)&&(theErr == noErr))
  381.         {
  382.         // grab the target FSSpec from the AEDesc:    
  383.         FSSpec    finalFSSpec;    
  384.         AEDesc     resultDesc;
  385.  
  386.         // there is only one selection here we get only the first AEDesc:
  387.         if ((theErr = AECoerceDesc(&(theReply.selection),typeFSS,&resultDesc)) == noErr)
  388.             if ((theErr = AEGetDescData ( &resultDesc, NULL, &finalFSSpec, sizeof ( FSSpec ), NULL )) == noErr)
  389.                 {
  390.                 // 'finalFSSpec' is the chosen volume…
  391.                 }
  392.         AEDisposeDesc(&resultDesc);
  393.         
  394.         theErr = NavDisposeReply(&theReply);
  395.         }
  396.         
  397.     DisposeRoutineDescriptor(eventUPP);
  398.     
  399.     return theErr;
  400. }
  401.  
  402.  
  403. // *****************************************************************************
  404. // *
  405. // *    DoCreateFolder()
  406. // *    
  407. // *****************************************************************************
  408. OSErr DoCreateFolder()
  409. {    
  410.     NavReplyRecord        theReply;
  411.     NavDialogOptions    dialogOptions;
  412.     OSErr                theErr = noErr;
  413.     NavEventUPP            eventUPP = NewNavEventProc(myEventProc);
  414.     
  415.     // use the default location for the dialog:
  416.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  417.     
  418.     GetIndString(dialogOptions.message,rAppStringsID,sCreateFolder);
  419.  
  420.     dialogOptions.preferenceKey = kNewFolderPrefKey;
  421.     
  422.     theErr = NavNewFolder(    NULL,
  423.                             &theReply,
  424.                             &dialogOptions,
  425.                             eventUPP, 
  426.                             (NavCallBackUserData)&gDocumentList);
  427.     if (theReply.validRecord)
  428.         {
  429.         // grab the target FSSpec from the AEDesc:    
  430.         FSSpec    finalFSSpec;    
  431.         AEDesc     resultDesc;
  432.  
  433.         // there is only one selection here so we get the first AEDesc:
  434.         if ((theErr = AECoerceDesc(&(theReply.selection),typeFSS,&resultDesc)) == noErr)
  435.             if ((theErr = AEGetDescData ( &resultDesc, NULL, &finalFSSpec, sizeof ( FSSpec ), NULL )) == noErr)
  436.                 {
  437.                 // 'finalFSSpec' is the newly created folder…
  438.                 }
  439.         AEDisposeDesc(&resultDesc);
  440.         
  441.         theErr = NavDisposeReply(&theReply);
  442.         }
  443.         
  444.     return theErr;
  445. }
  446.  
  447.  
  448. // *****************************************************************************
  449. // *
  450. // *    HandleCommandPopup()
  451. // *    
  452. // *****************************************************************************
  453. void HandleCommandPopup(ControlHandle thePopup, NavCBRecPtr callBackParms)
  454. {
  455.     OSErr     theErr = noErr;
  456.     short     selection = 0;
  457.     
  458.     selection = GetControlValue(thePopup)-1;
  459.     switch (selection)
  460.         {                                
  461.         case kNavCtlShowDesktop:
  462.         case kNavCtlScrollHome:
  463.         case kNavCtlScrollEnd:
  464.         case kNavCtlPageUp:
  465.         case kNavCtlPageDown:
  466.             theErr = NavCustomControl(callBackParms->context,selection,NULL);
  467.             break;
  468.         
  469.         case kNavCtlShowSelection:
  470.             theErr = NavCustomControl(callBackParms->context,kNavCtlShowSelection,NULL);
  471.             break;
  472.         
  473.         case kNavCtlOpenSelection:
  474.             {
  475.             AEDesc itemToOpen;
  476.             theErr = NavCustomControl(callBackParms->context,kNavCtlOpenSelection,&itemToOpen);
  477.             if (itemToOpen.descriptorType == typeFSS)
  478.                 {    
  479.                 // you may open the file as described by 'itemToOpen', or do whatever you want with it:
  480.                 AEDisposeDesc(&itemToOpen);
  481.                 }
  482.             break;
  483.             }
  484.             
  485.         case kNavCtlCancel:
  486.             theErr = NavCustomControl(callBackParms->context,kNavCtlCancel,NULL);
  487.             break;
  488.     
  489.         case kNavCtlAccept:
  490.             theErr = NavCustomControl(callBackParms->context,kNavCtlAccept,NULL);
  491.             break;
  492.         }
  493. }
  494.  
  495.  
  496. // *****************************************************************************
  497. // *
  498. // *    HandleCustomMouseDown()    
  499. // *
  500. // *****************************************************************************
  501. void HandleCustomMouseDown(NavCBRecPtr callBackParms)
  502. {
  503.     OSErr            theErr = noErr;
  504.     ControlHandle    whichControl;                
  505.     Point             where = callBackParms->eventData.event->where;    
  506.     short            theItem = 0;    
  507.     UInt16             firstItem = 0;
  508.     short            realItem = 0;
  509.     short            partCode = 0;
  510.         
  511.     GlobalToLocal(&where);
  512.     theItem = FindDialogItem(callBackParms->window,where);    // get the item number of the control
  513.     partCode = FindControl(where,callBackParms->window,&whichControl);    // get the control itself
  514.     
  515.     // ask NavServices for the first custom control's ID:
  516.     if (callBackParms->context != 0)    // always check to see if the context is correct
  517.         {
  518.         theErr = NavCustomControl(callBackParms->context,kNavCtlGetFirstControlID,&firstItem);    
  519.         realItem = theItem - firstItem + 1;        // map it to our DITL constants:    
  520.         }
  521.                 
  522.     if (realItem == kPopupCommand)
  523.         HandleCommandPopup(whichControl,callBackParms);
  524. }
  525.  
  526.  
  527. // *****************************************************************************
  528. // *
  529. // *    DoAddItem()    
  530. // *
  531. // *****************************************************************************
  532. Boolean DoAddItem(unsigned char* theData, short size)
  533. {
  534.     if (theData && gListItem)
  535.         {
  536.         Cell     theCell    = {0,0};
  537.         short      theRow;
  538.         
  539.         p2cstr((StringPtr)theData);
  540.         
  541.         if (LGetSelect(true,&theCell,gListItem))    // de-select all the currently selected items
  542.             {
  543.             LSetSelect(false,theCell,gListItem);        // deselect the first old item
  544.                 
  545.             theCell.v++;                                // move down one cell
  546.             
  547.             while (LGetSelect(true,&theCell,gListItem))    // find current selected item
  548.                 {
  549.                 if (LGetSelect(true,&theCell,gListItem))
  550.                     LSetSelect(false,theCell,gListItem);// deselect the next old item
  551.                 theCell.v++;
  552.                 }
  553.             }
  554.             
  555.         // insert data into (col 0, row x), add the item
  556.         theRow = LAddRow(1,256,gListItem);                // insert item into the new row
  557.         theCell.h = 0;
  558.         theCell.v = theRow;
  559.         LSetCell(theData,size,theCell,gListItem);
  560.         gNumItems++;
  561.         
  562.         c2pstr((Ptr)theData);
  563.         
  564.         LSetSelect(true,theCell,gListItem);            // select the newly added item
  565.         
  566.         LAutoScroll(gListItem);                        // scroll if necessary
  567.         
  568.         return true;
  569.         }
  570.     else
  571.         return false;
  572. }
  573.  
  574.  
  575. // *****************************************************************************
  576. // *
  577. // *    DoSearch()    
  578. // *
  579. // *****************************************************************************
  580. Boolean DoSearch( AEDesc searchDesc )
  581. {
  582.     OSErr        theErr = noErr;
  583.     Boolean        found = false;
  584.     FSSpec        finalSpec;
  585.     Cell         theCell = {0,0};
  586.     short         theLen;
  587.     
  588.     if ((theErr = AEGetDescData ( &searchDesc, NULL, &finalSpec, sizeof ( FSSpec ), NULL )) == noErr)
  589.         {
  590.         theLen = finalSpec.name[0];
  591.         p2cstr((StringPtr)finalSpec.name);
  592.         if (gListItem)
  593.             if (LSearch((Ptr)finalSpec.name, theLen, NULL, &theCell, gListItem))
  594.                 found = true;
  595.         c2pstr((Ptr)finalSpec.name);
  596.         }
  597.  
  598.     return found;
  599. }
  600.  
  601.  
  602. // *****************************************************************************
  603. // *
  604. // *    HandleAdd()    
  605. // *
  606. // *****************************************************************************
  607. void HandleAdd( NavCBRecPtr callBackParms, AEDescList theSelectionList )
  608. {
  609.     OSErr    theErr = noErr;
  610.     long    count = 0;
  611.     FSSpec    finalSpec;
  612.     UInt16     firstItem = 0;
  613.     Cell    beforeCell = {0,0};
  614.     Handle    itemH;
  615.     Rect    itemRect;
  616.     short    itemType;
  617.     
  618.     if ((theErr = AECountItems( &theSelectionList, &count )) == noErr)
  619.         for ( long index=1; index<=count; index++ )
  620.             {
  621.             AEDesc theItemDesc;
  622.             if ((theErr = AEGetNthDesc( &theSelectionList, index, typeFSS, NULL, &theItemDesc )) == noErr)
  623.                 {
  624.                 // put something in there:    
  625.                 if ((theErr = AEGetDescData ( &theItemDesc, NULL, &finalSpec, sizeof ( FSSpec ), NULL )) == noErr)    
  626.                     if (!DoSearch( theItemDesc ))
  627.                         {
  628.                         DoAddItem( finalSpec.name, finalSpec.name[0] );
  629.                         if (LGetSelect( true, &beforeCell, gListItem ))
  630.                             {
  631.                             // adjust the remove buttons:
  632.                             if ((theErr = NavCustomControl( callBackParms->context, kNavCtlGetFirstControlID, &firstItem )) == noErr)
  633.                                 {
  634.                                 GetDialogItem( callBackParms->window, firstItem + iRemoveButton + 1, &itemType, &itemH, &itemRect );
  635.                                 HiliteControl( (ControlHandle)itemH, 0 );
  636.                                 GetDialogItem( callBackParms->window, firstItem + iRemoveAllButton + 1, &itemType, &itemH, &itemRect );
  637.                                 HiliteControl( (ControlHandle)itemH, 0 );
  638.                                 }
  639.                             }
  640.                         }
  641.                     else
  642.                         SysBeep(5);    // item already in list
  643.                 AEDisposeDesc( &theItemDesc );
  644.                 }
  645.             }    
  646. }
  647.  
  648.  
  649. // *****************************************************************************
  650. // *
  651. // *    HandleRemoveAll()    
  652. // *
  653. // *****************************************************************************
  654. void HandleRemoveAll( NavCBRecPtr callBackParms )
  655. {
  656.     OSErr    theErr = noErr;
  657.     UInt16     firstItem = 0;
  658.     Handle    itemH;
  659.     Rect    itemRect;
  660.     short    itemType;
  661.     
  662.     if ( gListItem != NULL )
  663.         {
  664.         LDelRow( 0, 0, gListItem );
  665.         gNumItems = 0;
  666.         
  667.         // adjust the Remove Buttons
  668.         if ((theErr = NavCustomControl( callBackParms->context, kNavCtlGetFirstControlID, &firstItem )) == noErr)
  669.             {
  670.             GetDialogItem( callBackParms->window, firstItem + iRemoveButton + 1, &itemType, &itemH, &itemRect );
  671.             HiliteControl( (ControlHandle)itemH, 255 );
  672.             GetDialogItem( callBackParms->window, firstItem + iRemoveAllButton + 1, &itemType, &itemH, &itemRect );
  673.             HiliteControl( (ControlHandle)itemH, 255 );
  674.             }
  675.         }
  676. }
  677.  
  678.  
  679. // *****************************************************************************
  680. // *
  681. // *    HandleRemove()    
  682. // *
  683. // *****************************************************************************
  684. void HandleRemove( NavCBRecPtr callBackParms )
  685. {
  686.     OSErr    theErr     = noErr;
  687.     Cell    theCell = {0,0};
  688.     long     theID     = 0;
  689.     Boolean    result     = false;
  690.     UInt16     firstItem = 0;
  691.     Handle    removeH,removeAllH;
  692.     Rect    itemRect;
  693.     short    itemType;
  694.     
  695.     if (gListItem != NULL)
  696.         {
  697.         LGetSelect( true, &theCell,gListItem );            // find the first selected item
  698.         LDelRow(1,theCell.v, gListItem );
  699.         gNumItems--;
  700.         
  701.         while (LGetSelect( true, &theCell, gListItem ))    // find next selected item
  702.             {
  703.             LDelRow( 1, theCell.v, gListItem );
  704.             gNumItems--;
  705.             }
  706.             
  707.         // adjust the "Remove Button":
  708.         if ((theErr = NavCustomControl( callBackParms->context, kNavCtlGetFirstControlID, &firstItem )) == noErr)
  709.             {
  710.             GetDialogItem( callBackParms->window, firstItem + iRemoveButton + 1, &itemType, &removeH, &itemRect );        
  711.             GetDialogItem( callBackParms->window, firstItem + iRemoveAllButton + 1, &itemType, &removeAllH, &itemRect );
  712.             theCell.v = 0;
  713.             theCell.h = 0;
  714.             LSetSelect (true, theCell, gListItem);
  715.             if (LGetSelect( true, &theCell, gListItem ))    
  716.                 {
  717.                 HiliteControl( (ControlHandle)removeH, 0 );
  718.                 HiliteControl( (ControlHandle)removeAllH, 0 );
  719.                 }
  720.             else
  721.                 {
  722.                 HiliteControl( (ControlHandle)removeH, 255 );
  723.                 HiliteControl( (ControlHandle)removeAllH, 255 );
  724.                 }
  725.             }        
  726.         }
  727. }
  728.  
  729.  
  730. // *****************************************************************************
  731. // *
  732. // *    DoListMouseDown()    
  733. // *
  734. // *****************************************************************************
  735. Boolean DoListMouseDown( NavCBRecPtr callBackParms )
  736. {
  737.     Cell             whichCell={0,0}, beforeCell={0,0};
  738.     Point             myPt = callBackParms->eventData.event->where;
  739.     Boolean            result = true;
  740.     Handle            removeH,removeAllH;
  741.     Rect            itemRect;
  742.     short            itemType;
  743.     UInt16             firstItem = 0;
  744.     OSErr            theErr = noErr;
  745.     
  746.     SetPort( callBackParms->window );
  747.     GlobalToLocal( &myPt );
  748.                 
  749.     Boolean doubleClick = LClick(myPt, callBackParms->eventData.event->modifiers, gListItem );
  750.     whichCell = LLastClick( gListItem );
  751.     
  752.     // adjust the "Remove Button":
  753.     if ((theErr = NavCustomControl( callBackParms->context, kNavCtlGetFirstControlID, &firstItem )) == noErr)
  754.         {
  755.         GetDialogItem( callBackParms->window, firstItem + iRemoveButton + 1, &itemType, &removeH, &itemRect );
  756.         GetDialogItem( callBackParms->window, firstItem + iRemoveAllButton + 1, &itemType, &removeAllH, &itemRect );
  757.         }
  758.         
  759.     if (LGetSelect( true, &beforeCell, gListItem ))
  760.         {
  761.         HiliteControl( (ControlHandle)removeH, 0 );
  762.         HiliteControl( (ControlHandle)removeAllH, 0 );
  763.         }
  764.     else
  765.         {
  766.         HiliteControl( (ControlHandle)removeH, 255 );
  767.         HiliteControl( (ControlHandle)removeAllH, 255 );
  768.         }
  769.         
  770.     return result;
  771. }
  772.  
  773.  
  774. // *****************************************************************************
  775. // *
  776. // *    HandleAddRemoveCustomMouseDown()    
  777. // *
  778. // *****************************************************************************
  779. void HandleAddRemoveCustomMouseDown(NavCBRecPtr callBackParms)
  780. {
  781.     OSErr            theErr = noErr;
  782.     ControlHandle    whichControl;                
  783.     Point             where = callBackParms->eventData.event->where;    
  784.     short            theItem = 0;    
  785.     UInt16             firstItem = 0;
  786.     short            realItem = 0;
  787.     short            partCode = 0;
  788.     AEDescList         selectionList;
  789.     
  790.     GlobalToLocal(&where);
  791.     theItem = FindDialogItem( callBackParms->window, where );    // get the item number of the control
  792.     partCode = FindControl( where, callBackParms->window, &whichControl );    // get the control itself
  793.     
  794.     // ask NavServices for the first custom control's ID:
  795.     if ( callBackParms->context != 0 && ((theErr = NavCustomControl( callBackParms->context, kNavCtlGetFirstControlID, &firstItem )) == noErr))    // always check to see if the context is correct
  796.         {        
  797.         realItem = theItem - firstItem;        // map it to our DITL constants:    
  798.             
  799.         AdjustAddButton( callBackParms );
  800.         
  801.         switch (realItem)
  802.             {
  803.             case iList:
  804.                 DoListMouseDown( callBackParms );
  805.                 break;
  806.                 
  807.             case iAddButton:
  808.                 if ((theErr = NavCustomControl( callBackParms->context, kNavCtlGetSelection, &selectionList )) == noErr)            
  809.                     {
  810.                     HandleAdd( callBackParms, selectionList );
  811.                     AEDisposeDesc( &selectionList );
  812.                     }
  813.                 break;
  814.                 
  815.             case iRemoveButton:
  816.                 HandleRemove( callBackParms );
  817.                 break;
  818.                 
  819.             case iRemoveAllButton:
  820.                 HandleRemoveAll( callBackParms );
  821.                 break;
  822.                 
  823.             case iDoneButton:
  824.                 theErr = NavCustomControl(callBackParms->context,kNavCtlCancel,&firstItem);    
  825.                 break;
  826.             }
  827.         }
  828. }
  829.  
  830.  
  831. // *****************************************************************************
  832. // *
  833. // *    myEventProc()    
  834. // *
  835. // *****************************************************************************
  836. pascal void myCustomEventProc(    NavEventCallbackMessage callBackSelector, 
  837.                                 NavCBRecPtr callBackParms, 
  838.                                 NavCallBackUserData callBackUD)
  839. {
  840.     OSErr        theErr = noErr;
  841.     WindowPtr    pWindow = NULL;
  842.     Document**    docList;
  843.     Document*    theDoc = NULL;
  844.     short         index = 0;
  845.  
  846.     if (callBackUD != 0)
  847.         switch (callBackSelector)
  848.             {
  849.             case kNavCBEvent:
  850.                 {
  851.                 docList = (Document**)callBackUD;
  852.                 if (docList != NULL)
  853.                     switch (callBackParms->eventData.event->what)
  854.                         {
  855.                         case mouseDown:
  856.                             HandleCustomMouseDown(callBackParms);
  857.                             break;
  858.                         
  859.                         case updateEvt:
  860.                             pWindow = (WindowPtr)callBackParms->eventData.event->message;
  861.                             theDoc = docList[index];
  862.                             if (theDoc != NULL)
  863.                                 {
  864.                                 while ((theDoc->theWindow != pWindow) && (docList[index] != NULL))
  865.                                     {
  866.                                     index++;
  867.                                     theDoc = docList[index];
  868.                                     }
  869.                                 theDoc = docList[index];
  870.                                 if (theDoc != NULL)
  871.                                     UpdateWindow(theDoc);
  872.                                 }
  873.                             break;
  874.  
  875.                         default:
  876.                             break;
  877.                         }
  878.                 break;
  879.                 }
  880.     
  881.             case kNavCBCustomize:
  882.                 {                                
  883.                 // here are the desired dimensions for our custom area:
  884.                 short neededWidth = callBackParms->customRect.left + kCustomWidth;
  885.                 short neededHeight = callBackParms->customRect.top + kCustomHeight;
  886.                 
  887.                 // check to see if this is the first round of negotiations:
  888.                 if ((callBackParms->customRect.right == 0) && (callBackParms->customRect.bottom == 0))
  889.                     {
  890.                     // it is, so tell NavServices what dimensions we want:
  891.                     callBackParms->customRect.right = neededWidth;
  892.                     callBackParms->customRect.bottom = neededHeight;
  893.                     }
  894.                 else
  895.                     {
  896.                     // we are in the middle of negotiating:
  897.                     if (gLastTryWidth != callBackParms->customRect.right)
  898.                         if (callBackParms->customRect.right < neededWidth)    // is NavServices width too small for us?
  899.                             callBackParms->customRect.right = neededWidth;
  900.  
  901.                     if (gLastTryHeight != callBackParms->customRect.bottom)    // is NavServices height too small for us?
  902.                         if (callBackParms->customRect.bottom < neededHeight)
  903.                             callBackParms->customRect.bottom = neededHeight;
  904.                     }
  905.                 
  906.                 // remember our last size so the next time we can re-negotiate:
  907.                 gLastTryWidth = callBackParms->customRect.right;
  908.                 gLastTryHeight = callBackParms->customRect.bottom;    
  909.                 break;
  910.                 }
  911.                 
  912.             case kNavCBStart:
  913.                 {
  914.                 short    itemType;
  915.                 Rect    itemRect;
  916.                 Handle    itemH;
  917.                 UInt16     firstItem = 0;    
  918.                 short    realItem = 0;
  919.                 
  920.                 // add the rest of the custom controls via the DITL resource list:
  921.                 gDitlList = GetResource('DITL',kControlListID);
  922.                 if ((gDitlList != NULL)&&(ResError() == noErr))
  923.                     if ((theErr = NavCustomControl(callBackParms->context,kNavCtlAddControlList,gDitlList)) == noErr)
  924.                         {
  925.                         theErr = NavCustomControl(callBackParms->context,kNavCtlGetFirstControlID,&firstItem);    // ask NavServices for our first control ID
  926.                                 
  927.                         // set the command popup selection:
  928.                         realItem = firstItem + kPopupCommand;
  929.                         GetDialogItem(callBackParms->window,realItem,&itemType,&itemH,&itemRect);
  930.                         SetControlValue((ControlHandle)itemH,1);
  931.                         }
  932.                     
  933.                 // the dialog is starting up, let's override the default popup menu selection:
  934.                 UInt16 itemToSelect = kNavAllReadableFiles;
  935.                 theErr = NavCustomControl(callBackParms->context,kNavCtlSelectAllType,&itemToSelect);
  936.                 break;
  937.                 }
  938.                 
  939.             case kNavCBTerminate:
  940.                 // release our appended popup menu:
  941.                 if (gDitlList)
  942.                     ReleaseResource(gDitlList);        
  943.                 if (gPopupMenu)
  944.                     DisposeMenu(gPopupMenu);        
  945.                 break;
  946.             }
  947. }
  948.  
  949.  
  950. // *****************************************************************************
  951. // *
  952. // *    AdjustAddButton()    
  953. // *
  954. // *****************************************************************************
  955. void AdjustAddButton( NavCBRecPtr callBackParms )
  956. {
  957.     OSErr            theErr = noErr;
  958.     AEDescList         selectionList;
  959.     Handle            itemH;
  960.     Rect            itemRect;
  961.     short            itemType;
  962.     FSSpec            finalSpec;
  963.     AEDesc            resultDesc;
  964.     UInt16             firstItem = 0;
  965.     long            itemCount = 0;
  966.     
  967.     // update the button states:
  968.     if ((theErr = NavCustomControl( callBackParms->context, kNavCtlGetFirstControlID, &firstItem )) == noErr)
  969.         if ((theErr = NavCustomControl( callBackParms->context, kNavCtlGetSelection, &selectionList )) == noErr)
  970.             {
  971.             GetDialogItem( callBackParms->window, firstItem + iAddButton + 1, &itemType, &itemH, &itemRect );    
  972.             if (( theErr = AECountItems( &selectionList, &itemCount )) == noErr )    
  973.                 {
  974.                 if (itemCount == 1)
  975.                     {
  976.                     if ((theErr = AEGetNthDesc( &selectionList, 1, typeFSS, NULL, &resultDesc)) == noErr)
  977.                         {
  978.                         if ((theErr = AEGetDescData ( &resultDesc, NULL, &finalSpec, sizeof ( FSSpec ), NULL )) == noErr)
  979.                             {
  980.                             if (finalSpec.name[0] == 0)
  981.                                 HiliteControl( (ControlHandle)itemH, 255 );    // the object is a folder, disable add:
  982.                             else
  983.                                 HiliteControl( (ControlHandle)itemH, 0 );    // the object is a file, enable add:
  984.                             }
  985.                         AEDisposeDesc(&resultDesc);
  986.                         }
  987.                     }
  988.                 else
  989.                     HiliteControl( (ControlHandle)itemH, 0 );    // we have current selection
  990.                 }
  991.             else
  992.                 HiliteControl( (ControlHandle)itemH, 255 );        // no current selection
  993.                     
  994.             AEDisposeDesc( &selectionList );
  995.             }
  996. }
  997.  
  998.  
  999. // *****************************************************************************
  1000. // *
  1001. // *    myCustomAddRemoveEventProc()    
  1002. // *
  1003. // *****************************************************************************
  1004. pascal void myCustomAddRemoveEventProc(    NavEventCallbackMessage callBackSelector, 
  1005.                                         NavCBRecPtr callBackParms, 
  1006.                                         NavCallBackUserData callBackUD)
  1007. {
  1008.     OSErr        theErr = noErr;
  1009.     WindowPtr    pWindow = (WindowPtr)callBackParms->eventData.event->message;
  1010.     
  1011.     // for managing our windows:
  1012.     Document**    docList;
  1013.     Document*    theDoc = NULL;
  1014.     
  1015.     // for handling dialog items:
  1016.     short        itemType;
  1017.     Rect        itemRect;
  1018.     Handle        itemH;
  1019.     UInt16         firstItem = 0;    
  1020.     short        realItem = 0;
  1021.         
  1022.     short hOffset = 0;
  1023.     short vOffset = 0;
  1024.                         
  1025.     if (callBackUD != 0)
  1026.         switch (callBackSelector)
  1027.             {
  1028.             case kNavCBEvent:
  1029.                 {    
  1030.                 switch (callBackParms->eventData.event->what)
  1031.                     {
  1032.                     case mouseDown:
  1033.                         HandleAddRemoveCustomMouseDown(callBackParms);
  1034.                         break;
  1035.                     
  1036.                     case updateEvt:
  1037.                         if (pWindow == callBackParms->window)
  1038.                             {
  1039.                             // ask NavServices for our first control ID
  1040.                             if ((theErr = NavCustomControl(callBackParms->context, kNavCtlGetFirstControlID, &firstItem )) == noErr)
  1041.                                 {
  1042.                                 LUpdate( callBackParms->window->visRgn, gListItem );
  1043.                                 
  1044.                                 // set the command popup selection:
  1045.                                 realItem = firstItem + iList + 1;
  1046.                                 GetDialogItem(callBackParms->window,realItem,&itemType,&itemH,&itemRect);
  1047.                                 InsetRect(&itemRect,-1,-1);
  1048.                                 FrameRect(&itemRect);
  1049.                                 }
  1050.                             }
  1051.                         else
  1052.                             {
  1053.                             short index = 0;    
  1054.                             docList = (Document**)callBackUD;
  1055.                             if (docList != NULL)
  1056.                                 {
  1057.                                 theDoc = docList[index];
  1058.                                 if (theDoc != NULL)
  1059.                                     {
  1060.                                     while ((theDoc->theWindow != pWindow) && (docList[index] != NULL))
  1061.                                         {
  1062.                                         index++;
  1063.                                         theDoc = docList[index];
  1064.                                         }
  1065.                                     theDoc = docList[index];
  1066.                                     if (theDoc != NULL)
  1067.                                         UpdateWindow(theDoc);
  1068.                                     }
  1069.                                 }
  1070.                             }
  1071.                         break;
  1072.  
  1073.                     default:
  1074.                         break;
  1075.                     }
  1076.                 break;
  1077.                 }
  1078.     
  1079.             case kNavCBCustomize:
  1080.                 {                                
  1081.                 // here are the desired dimensions for our custom area:
  1082.                 short neededWidth = callBackParms->customRect.left + kAddRemoveCustomWidth;
  1083.                 short neededHeight = callBackParms->customRect.top + kAddRemoveCustomHeight;
  1084.                 
  1085.                 // check to see if this is the first round of negotiations:
  1086.                 if ((callBackParms->customRect.right == 0) && (callBackParms->customRect.bottom == 0))
  1087.                     {
  1088.                     // it is, so tell NavServices what dimensions we want:
  1089.                     callBackParms->customRect.right = neededWidth;
  1090.                     callBackParms->customRect.bottom = neededHeight;
  1091.                     }
  1092.                 else
  1093.                     {
  1094.                     // we are in the middle of negotiating:
  1095.                     if (gLastTryWidth != callBackParms->customRect.right)
  1096.                         if (callBackParms->customRect.right < neededWidth)    // is NavServices width too small for us?
  1097.                             callBackParms->customRect.right = neededWidth;
  1098.  
  1099.                     if (gLastTryHeight != callBackParms->customRect.bottom)    // is NavServices height too small for us?
  1100.                         if (callBackParms->customRect.bottom < neededHeight)
  1101.                             callBackParms->customRect.bottom = neededHeight;
  1102.                     }
  1103.                 
  1104.                 // remember our last size so the next time we can re-negotiate:
  1105.                 gLastTryWidth = callBackParms->customRect.right;
  1106.                 gLastTryHeight = callBackParms->customRect.bottom;    
  1107.                 break;
  1108.                 }
  1109.                 
  1110.             case kNavCBAdjustRect:
  1111.                 if (gListItem != NULL)
  1112.                     {
  1113.                     Rect             newRect;
  1114.                     Rect             finalRect;
  1115.                     Cell            theCell = {0,0};
  1116.                     ControlHandle     scrollBar = (*gListItem)->vScroll;
  1117.                     
  1118.                     theErr = NavCustomControl(callBackParms->context, kNavCtlGetFirstControlID, &firstItem );    // ask NavServices for our first control ID
  1119.                     realItem = firstItem + iList + 1;
  1120.                     GetDialogItem( callBackParms->window, realItem, &itemType, &itemH, &itemRect );
  1121.                         
  1122.                     // change the list's rect:
  1123.                     newRect = itemRect;
  1124.                     newRect.right -= 15;
  1125.                     (*gListItem)->rView = newRect;
  1126.                     
  1127.                     // change the list's scrollbar control:
  1128.                     InsetRect(&itemRect,-1,-1);
  1129.                     SetRect( &finalRect, itemRect.right-16, itemRect.top, itemRect.right, itemRect.bottom );
  1130.                     (*scrollBar)->contrlRect = finalRect;
  1131.                              
  1132.                     LUpdate( callBackParms->window->visRgn, gListItem );
  1133.                     LActivate( true, gListItem );
  1134.                                         
  1135.                     gOriginalRect = callBackParms->customRect;
  1136.                     }
  1137.                 break;
  1138.                 
  1139.             case kNavCBStart:
  1140.                 // add the rest of the custom controls via the DITL resource list:
  1141.                 gDitlList = GetResource('DITL',kAddRemoveControlListID);
  1142.                 if (gDitlList != NULL && ResError() == noErr)
  1143.                     if ((theErr = NavCustomControl(callBackParms->context,kNavCtlAddControlList,gDitlList)) == noErr)
  1144.                         {
  1145.                         theErr = NavCustomControl(callBackParms->context,kNavCtlGetFirstControlID,&firstItem);    // ask NavServices for our first control ID
  1146.                                 
  1147.                         realItem = firstItem + iList + 1;
  1148.                         GetDialogItem(callBackParms->window,realItem,&itemType,&itemH,&itemRect);
  1149.  
  1150.                         Rect    tempRect;    // used as modify the list rect
  1151.                         Rect    dataBounds;    // bounds of the list
  1152.                         Point     theCell;
  1153.                         
  1154.                         tempRect = itemRect;
  1155.                         tempRect.right = tempRect.right - 15;
  1156.                         if (tempRect.right <= (tempRect.left + 15)) 
  1157.                             tempRect.right = tempRect.left + 15;
  1158.                             
  1159.                         InsetRect(&tempRect,-1,-1);
  1160.                         FrameRect(&tempRect);
  1161.                         InsetRect(&tempRect,1,1);
  1162.                         
  1163.                         SetRect(&dataBounds,0,0,1,0);    // empty list
  1164.                         
  1165.                         theCell.h = tempRect.right - tempRect.left;
  1166.                         theCell.v = 16;
  1167.                         
  1168.                         gListItem = NULL;
  1169.                         gListItem = LNew(&tempRect,&dataBounds,theCell,0,callBackParms->window,true,false,false,true);
  1170.                         if (gListItem != NULL)
  1171.                             {
  1172.                             gNumItems = 0;
  1173.                             
  1174.                             (*gListItem)->selFlags = lNoNilHilite + lUseSense;
  1175.     
  1176.                             LSetDrawingMode(true,gListItem);            // list gets automatically drawn
  1177.                             
  1178.                             theCell.v = 0;
  1179.                             theCell.h = 0;
  1180.                             LSetSelect(true,theCell,gListItem);    // default selection to 0,0
  1181.                             LAutoScroll(gListItem);                // keep scrolling so the first property is visible
  1182.                             
  1183.                             (void)LClick(theCell,0,gListItem);    // click in negative space to indicate the list is blank
  1184.                             }
  1185.                             
  1186.                         // disable the "Remove All Button":
  1187.                         GetDialogItem( callBackParms->window, firstItem + iRemoveAllButton + 1, &itemType, &itemH, &itemRect );
  1188.                         HiliteControl( (ControlHandle)itemH, 255 );
  1189.                                 
  1190.                         // disable the "Remove Button":
  1191.                         GetDialogItem( callBackParms->window, firstItem + iRemoveButton + 1, &itemType, &itemH, &itemRect );
  1192.                         HiliteControl( (ControlHandle)itemH, 255 );
  1193.                         
  1194.                         AdjustAddButton( callBackParms );
  1195.                         }
  1196.                 break;
  1197.                 
  1198.             case kNavCBTerminate:
  1199.                 if (gDitlList)
  1200.                     ReleaseResource(gDitlList);
  1201.                 if (gListItem != NULL)
  1202.                     LDispose(gListItem);
  1203.                     
  1204.                 gListItem = NULL;
  1205.                 gNumItems = 0;
  1206.                 break;
  1207.             }
  1208. }
  1209.  
  1210.  
  1211. // *****************************************************************************
  1212. // *
  1213. // *    DoCustomAddRemove()
  1214. // *
  1215. // *    This is a "primitive" example of how you would add an Add/Remove
  1216. // *    human interface to NavGetFile().
  1217. // *    
  1218. // *****************************************************************************
  1219. OSErr DoCustomAddRemove( )
  1220. {
  1221.     NavReplyRecord        theReply;
  1222.     NavDialogOptions    dialogOptions;
  1223.     OSErr                theErr = noErr;
  1224.     NavTypeListHandle    typeList = NULL;
  1225.     long                count = 0;
  1226.     NavEventUPP            eventUPP = NewNavEventProc(myCustomAddRemoveEventProc);
  1227.     
  1228.     // default behavior for browser and dialog:
  1229.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  1230.  
  1231.     GetIndString((unsigned char*)&dialogOptions.windowTitle,rAppStringsID,sAddRemoveTitle);
  1232.  
  1233.     dialogOptions.dialogOptionFlags += kNavNoTypePopup;
  1234.     dialogOptions.dialogOptionFlags -= kNavAllowPreviews;
  1235.     dialogOptions.dialogOptionFlags += kNavDontAutoTranslate;
  1236.     
  1237.     theErr = NavGetFile(NULL,    // use system's default location
  1238.                         &theReply,
  1239.                         &dialogOptions,
  1240.                         eventUPP,
  1241.                         NULL,    // no custom previews
  1242.                         NULL,
  1243.                         NULL,
  1244.                         (NavCallBackUserData)&gDocumentList);
  1245.  
  1246.     DisposeRoutineDescriptor(eventUPP);
  1247.  
  1248.     if (theReply.validRecord && theErr == noErr)
  1249.         {
  1250.         // since we allow for multiple objects to be returned,
  1251.         // grab the target FSSpecs from 'theReply.fileRef' list for opening:    
  1252.         FSSpec    finalFSSpec;    
  1253.         AEDesc     resultDesc;
  1254.  
  1255.         // we are ready to open the document(s), grab information about each file for opening:
  1256.         theErr = AECountItems(&(theReply.selection),&count);
  1257.         for (long index=1;index<=count;index++)
  1258.             {
  1259.             if ((theErr = AEGetNthDesc(&(theReply.selection),index,typeFSS,NULL,&resultDesc)) == noErr)
  1260.                 if ((theErr = AEGetDescData ( &resultDesc, NULL, &finalFSSpec, sizeof ( FSSpec ), NULL )) == noErr)
  1261.                     {
  1262.                     //..
  1263.                     }
  1264.                     
  1265.             theErr = AEDisposeDesc(&resultDesc);
  1266.             }
  1267.         
  1268.         theErr = NavDisposeReply(&theReply);    // clean up after ourselves    
  1269.         }
  1270.     
  1271.     return theErr;
  1272. }
  1273.  
  1274.  
  1275. // *****************************************************************************
  1276. // *
  1277. // *    DoCustomOpen()
  1278. // *    
  1279. // *****************************************************************************
  1280. OSErr DoCustomOpen()
  1281. {    
  1282.     NavReplyRecord        theReply;
  1283.     NavDialogOptions    dialogOptions;
  1284.     OSErr                theErr = noErr;
  1285.     NavTypeListHandle    typeList = NULL;
  1286.     long                count = 0;
  1287.     NavEventUPP            eventUPP = NewNavEventProc(myCustomEventProc);
  1288.     
  1289.     // default behavior for browser and dialog:
  1290.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  1291.  
  1292.     GetIndString((unsigned char*)&dialogOptions.clientName,rAppStringsID,sApplicationName);
  1293.     
  1294.     typeList = (NavTypeListHandle)GetResource(kOpenRsrcType,kOpenRsrcID);
  1295.  
  1296.     theErr = NavGetFile(NULL,    // use system's default location
  1297.                         &theReply,
  1298.                         &dialogOptions,
  1299.                         eventUPP,
  1300.                         NULL,    // no custom previews
  1301.                         NULL,
  1302.                         typeList,
  1303.                         (NavCallBackUserData)&gDocumentList);
  1304.  
  1305.     DisposeRoutineDescriptor(eventUPP);
  1306.  
  1307.     if (theReply.validRecord && theErr == noErr)
  1308.         {
  1309.         // since we allow for multiple objects to be returned,
  1310.         // grab the target FSSpecs from 'theReply.fileRef' list for opening:    
  1311.         FSSpec    finalFSSpec;    
  1312.         AEDesc     resultDesc;
  1313.         FInfo    fileInfo;
  1314.  
  1315.         // we are ready to open the document(s), grab information about each file for opening:
  1316.         theErr = AECountItems(&(theReply.selection),&count);
  1317.         for (long index=1;index<=count;index++)
  1318.             {
  1319.             if ((theErr = AEGetNthDesc(&(theReply.selection),index,typeFSS,NULL,&resultDesc)) == noErr)
  1320.                 {
  1321.                 if ((theErr = AEGetDescData ( &resultDesc, NULL, &finalFSSpec, sizeof ( FSSpec ), NULL )) == noErr)
  1322.                     // decide if the doc we are opening is a 'PICT' or 'TEXT':
  1323.                     if ((theErr = FSpGetFInfo(&finalFSSpec,&fileInfo)) == noErr)
  1324.                         {
  1325.                         if (fileInfo.fdType == kFileType)
  1326.                             (void)DoOpenFile(&finalFSSpec,false);
  1327.                         else
  1328.                             if (fileInfo.fdType == kFileTypePICT)
  1329.                                 (void)DoOpenFile(&finalFSSpec,true);
  1330.                             else
  1331.                                 {
  1332.                                 // error:
  1333.                                 // if we got this far, the document is a type we can't open and
  1334.                                 // (most likely) built-in translation was turned off.
  1335.                                 // You can alert the user that this returned selection or file spec
  1336.                                 // needs translation.
  1337.                                 }
  1338.                         }
  1339.                 theErr = AEDisposeDesc(&resultDesc);
  1340.                 }
  1341.             }
  1342.         
  1343.         theErr = NavDisposeReply(&theReply);    // clean up after ourselves    
  1344.         }
  1345.  
  1346.     if (typeList != NULL)
  1347.         ReleaseResource((Handle)typeList);
  1348.         
  1349.     return theErr;
  1350. }
  1351.  
  1352.  
  1353. // *****************************************************************************
  1354. // *
  1355. // *    DoAbout()
  1356. // *    
  1357. // *****************************************************************************
  1358. void DoAbout()
  1359. {
  1360.     GrafPtr        savePort;
  1361.     DialogPtr    aboutDialog;
  1362.     short        itemHit = 0;
  1363.     Handle        itemH;
  1364.     short        itemType;
  1365.     Rect        itemRect;
  1366.     
  1367.     SetCursor(&qd.arrow);
  1368.     aboutDialog = GetNewDialog(rAboutID,nil,(WindowRef)-1);
  1369.     
  1370.     GetPort(&savePort);
  1371.  
  1372.     SetPort((GrafPtr)aboutDialog);
  1373.  
  1374.     AdornButton(aboutDialog,dOK);
  1375.  
  1376.     GetDialogItem(aboutDialog,iIconSuite,&itemType,&itemH,&itemRect);
  1377.     DrawIconSuite(rIconSuite,itemRect);
  1378.                     
  1379.     do ModalDialog(nil,&itemHit);
  1380.  
  1381.     while(itemHit != dOK);
  1382.     
  1383.     SetPort(savePort);
  1384.     DisposeDialog(aboutDialog);
  1385. }
  1386.  
  1387.  
  1388. // *****************************************************************************
  1389. // *
  1390. // *    DoMenuCommand()
  1391. // *
  1392. // *****************************************************************************
  1393. void DoMenuCommand(long select)
  1394. {    
  1395.     short        theMenuID, theItem;
  1396.     MenuHandle    theMenu;
  1397.     Str255        theName;
  1398.     WindowPtr    theWindow;
  1399.     Document*    theDocument = nil;
  1400.     OSStatus    theErr = noErr;
  1401.  
  1402.     gCanUndoDrag = slUndoDrag;
  1403.     AdjustMenus();
  1404.     
  1405.     theDocument = IsDocumentWindow(theWindow = (WindowPtr)FrontWindow());
  1406.  
  1407.     theItem   = LoWord(select);
  1408.     theMenuID = HiWord(select);
  1409.     theMenu   = GetMenuHandle(theMenuID);
  1410.     switch(theMenuID)
  1411.         {
  1412.         case idAppleMenu:
  1413.             switch(theItem)
  1414.                 {
  1415.                 case AboutItem:
  1416.                     DoAbout();
  1417.                     break;
  1418.                 default:
  1419.                     GetMenuItemText(GetMenuHandle(idAppleMenu),theItem,(unsigned char*)&theName);
  1420.                     OpenDeskAcc(theName);
  1421.                 }
  1422.             break;
  1423.             
  1424.         case idFileMenu:
  1425.             switch(theItem)
  1426.                 {
  1427.                 case NewItem:
  1428.                     DoNewDocument(false);
  1429.                     AdjustMenus();
  1430.                     break;
  1431.                     
  1432.                 case OpenItem:
  1433.                     if (gNavServicesExists)
  1434.                         theErr = DoOpenDocument();
  1435.                     else    
  1436.                         (void)DoOpenDocumentTheOldWay();
  1437.                     AdjustMenus();        
  1438.                     break;
  1439.                     
  1440.                 case CloseItem:
  1441.                     if (theDocument)
  1442.                         {
  1443.                         CloseDocument(theDocument,false);
  1444.                         AdjustMenus();
  1445.                         DrawMenuBar();
  1446.                         }
  1447.                     break;
  1448.                     
  1449.                 case SaveItem:
  1450.                     if (theDocument)
  1451.                         DoSaveDocument(theDocument);
  1452.                     break;
  1453.                 
  1454.                 case SaveACopyItem:
  1455.                     if (theDocument)
  1456.                         {
  1457.                         if (gNavServicesExists)
  1458.                             theErr = SaveACopyDocument(theDocument);
  1459.                         else
  1460.                             (void)SaveACopyDocumentTheOldWay(theDocument);
  1461.                         
  1462.                         if (theErr == memFullErr)
  1463.                             {
  1464.                             (void)SaveACopyDocumentTheOldWay(theDocument);
  1465.                             theErr = noErr;
  1466.                             }
  1467.                         }
  1468.                     break;
  1469.     
  1470.                 case RevertItem:
  1471.                     DisableUndoDrag();
  1472.                     if (theDocument)
  1473.                         {
  1474.                         if (gNavServicesExists)
  1475.                             DoRevertDocument(theDocument);
  1476.                         else
  1477.                             DoRevertDocumentTheOldWay(theDocument);
  1478.                         }
  1479.                     break;
  1480.  
  1481.                 case DictionaryItem:
  1482.                     theErr = DoSelectDictionary();
  1483.                     break;
  1484.  
  1485.                 case QuitItem:
  1486.                     gQuitting = true;
  1487.                     while ((gQuitting) && (theDocument = IsDocumentWindow((WindowPtr)FrontWindow())))
  1488.                         CloseDocument(theDocument,true);
  1489.                     if (gQuitting)
  1490.                         gQuit = true;
  1491.                     break;
  1492.                 }
  1493.             break;
  1494.             
  1495.         case idEditMenu:
  1496.             switch(theItem)
  1497.                 {
  1498.                 case iUndo:
  1499.                     DoUndoDrag();
  1500.                     break;
  1501.                     
  1502.                 case iCut:
  1503.                     if ((theDocument)&&(theDocument->theTE != NULL))
  1504.                         {
  1505.                         DisableUndoDrag();
  1506.                         myTECut(theDocument->theTE);
  1507.                         }
  1508.                     break;
  1509.                     
  1510.                 case iCopy:
  1511.                     if (theDocument)
  1512.                         TECopy(theDocument->theTE);
  1513.                     break;
  1514.                     
  1515.                 case iPaste:
  1516.                     if ((theDocument)&&(theDocument->theTE != NULL))
  1517.                         if (!DoPaste())
  1518.                             {
  1519.                             DisableUndoDrag();
  1520.                             myTEPaste(theDocument->theTE,0L,0L);
  1521.                             }
  1522.                     break;
  1523.                     
  1524.                 case iClear:
  1525.                     if ((theDocument)&&(theDocument->theTE != NULL))
  1526.                         {
  1527.                         DisableUndoDrag();
  1528.                         TEDelete(theDocument->theTE);
  1529.                         }
  1530.                     break;
  1531.                     
  1532.                 case iSelectAll:
  1533.                     if ((theDocument)&&(theDocument->theTE != NULL))
  1534.                         DoSelectAllDocument(theDocument);
  1535.                     break;
  1536.                 }
  1537.             break;
  1538.  
  1539.         case idUtilsMenu:
  1540.             switch (theItem)
  1541.                 {
  1542.                 case iSelectDir:
  1543.                     theErr = DoSelectDirectory();
  1544.                     break;
  1545.                 case iSelectVol:
  1546.                     theErr = DoSelectVolume();
  1547.                     break;
  1548.                 case iSelectObject:
  1549.                     theErr = DoSelectObject();
  1550.                     break;
  1551.                 case iCreateFolder:
  1552.                     theErr = DoCreateFolder();
  1553.                     break;
  1554.                 case iCustomOpen:
  1555.                     theErr = DoCustomOpen();
  1556.                     break;
  1557.                 case iAddFiles:
  1558.                     theErr = DoCustomAddRemove();
  1559.                     break; 
  1560.                 }
  1561.             break;
  1562.         }        
  1563.  
  1564.     if ( theErr == memFullErr )
  1565.         DoLowMemAlert( );
  1566.     
  1567.     if (theDocument = IsDocumentWindow((WindowPtr)FrontWindow()))
  1568.         if (theDocument->theTE != NULL)
  1569.             TEGetHiliteRgn(theDocument->hiliteRgn,theDocument->theTE);
  1570.  
  1571.     HiliteMenu(0);
  1572.     
  1573.     gCanUndoDrag = slCantUndo;
  1574. }
  1575.  
  1576.